

package yf.mall.service.impl;

import com.yf.response.RRException;
import org.springframework.context.annotation.Lazy;
import org.springframework.transaction.annotation.Transactional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.alibaba.excel.EasyExcel;
import yf.mall.dao.LotteryRecordDao;
import yf.mall.dao.MallCardDao;
import yf.mall.entity.*;
import yf.mall.enums.LotteryActStatusEnum;
import yf.mall.enums.LotteryGoodsStatusEnum;
import yf.mall.enums.LotteryRecordStatusEnum;
import yf.mall.service.*;
import yf.mall.vo.down.LotteryActDown;

import java.text.SimpleDateFormat;
import java.util.*;
import java.net.URLEncoder;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.stream.Collectors;

import yf.mall.dao.LotteryActDao;
import yf.mall.vo.LotteryActVo;
import com.yf.service.impl.BaseServiceImpl;

/**
 * 账户记录Service实现类
 *
 * @author hxf
 * @email 505860922@qq.com
 * @date Thu Aug 20 10:29:43 CST 2020
 */
@Service
public class LotteryActServiceImpl extends BaseServiceImpl<LotteryActEntity> implements LotteryActService {

    private LotteryActDao dao;


    @Autowired
    public void setDao(LotteryActDao dao) {
        this.dao = dao;
        super.setBaseDao(dao);
    }


    @Override
    public List<LotteryActVo> findVo(LotteryActVo vo) {
        return dao.findVo(vo);
    }

    @Override
    public LotteryActVo getVo(Long id) {
        return dao.getVo(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int saveVo(LotteryActVo vo) {
        return dao.save(vo.getEntity());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateVo(LotteryActVo vo) {
        return dao.update(vo.getEntity());
    }

    /**
     * 给所有的抽奖记录生成奖品
     *
     * @param actId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateLottery(Long actId) {
        updateLotteryRecord(actId);
    }

    /**
     * 恢复所有没有抽奖的记录
     *
     * @param id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void renew(Long id) {
        //获取所有没有抽奖的记录
        List<LotteryRecordEntity> recordEntities = lotteryRecordDao.findByUserIdAndActIdAndIsLotteryAndStatus(id);
        if (recordEntities != null && recordEntities.size() > 0) {

            for (LotteryRecordEntity lotteryRecordEntity : recordEntities) {
                lotteryRecordEntity.setGoodsName(null);
                lotteryRecordEntity.setGoodsId(null);
                lotteryRecordEntity.setBandGoodsId(null);
                lotteryRecordEntity.setIsLottery(null);
                lotteryRecordEntity.setTime(new Date());
                lotteryRecordDao.update(lotteryRecordEntity);
            }

        }
    }

    @Override
    public Boolean lotteryAct() {
        List<LotteryActEntity> acts = this.dao.findByStatusAndToday(LotteryActStatusEnum.OPEN.getIndex(), new Date());
        if (acts!=null && acts.size()>0){
            return true;
        }else return false;
    }


    /**
     * 将抽奖记录附上奖品
     * @param id
     */
    private void updateLotteryRecord(Long id) {
        // 获取所有的抽奖记录
        List<LotteryRecordEntity> lotteryRecordEntities = lotteryRecordDao.findByActId(id);
        if (lotteryRecordEntities != null && lotteryRecordEntities.size() > 0) {
            // 获取所有开启的抽奖奖品
            List<LotteryGoodsEntity> lotteryGoodsEntities = lotteryGoodsService.findByActId(id, LotteryGoodsStatusEnum.YES.getIndex());
            if (lotteryGoodsEntities != null && lotteryGoodsEntities.size() > 0) {
                Map<LotteryGoodsEntity, Integer> goodsMap = new LinkedHashMap();
                for (LotteryGoodsEntity lotteryGoodsEntity : lotteryGoodsEntities) {
                    goodsMap.put(lotteryGoodsEntity, lotteryGoodsEntity.getPr());
                }
                for (LotteryRecordEntity lotteryRecordEntity : lotteryRecordEntities) {
                    LotteryGoodsEntity goodsEntity = lotteryGoodsService.findMaxGoods(id);
                    lotteryRecordEntity.setGoodsName(goodsEntity.getName());
                    lotteryRecordEntity.setGoodsId(goodsEntity.getId());
                    if (goodsEntity.getGoodsId() != null) {
                        lotteryRecordEntity.setBandGoodsId(goodsEntity.getGoodsId());
                    }
                    lotteryRecordEntity.setIsLottery(LotteryRecordStatusEnum.NOT_LOTTERY.getIndex());
                    lotteryRecordDao.update(lotteryRecordEntity);
                }
                Random random = new Random();
                // 生成奖品
                createGoods(lotteryRecordEntities, goodsMap, random);
            } else {
                throw new RRException("请添加产品或奖品启用");
            }
        }
    }

    /**
     * 随机将记录赋予奖品
     *
     * @param goodsMap
     * @param random
     */
    private void createGoods(List<LotteryRecordEntity> recordEntities, Map<LotteryGoodsEntity, Integer> goodsMap, Random random) {
        for (Map.Entry<LotteryGoodsEntity, Integer> goodsEntry : goodsMap.entrySet()) {
            Integer value = goodsEntry.getValue();
            LotteryGoodsEntity goodsEntity = goodsEntry.getKey();
            //获取已经生成奖品的记录
            Integer count = lotteryRecordDao.findByActIdAndGoodsId(goodsEntity.getActId(), goodsEntity.getId());

            if (value != null && value > 0 && count < value) {
                // 可以省多少分奖品
                for (Integer i = 0; i < value - count; i++) {
                    if (recordEntities.equals(null) || recordEntities.size() <= 0) {
                        return;
                    }
                    //判断是否有对应的随机数
                    int nextInt = random.nextInt(recordEntities.size());
                    if (nextInt < recordEntities.size()) {
                        //获取对应随机数的抽奖记录
                        LotteryRecordEntity lotteryRecordEntity = recordEntities.get(nextInt);
                        if (lotteryRecordEntity != null) {
                            if (goodsEntity != null) {
                                lotteryRecordEntity.setGoodsName(goodsEntity.getName());
                                lotteryRecordEntity.setGoodsId(goodsEntity.getId());
                                if (goodsEntity.getGoodsId() != null) {
                                    lotteryRecordEntity.setBandGoodsId(goodsEntity.getGoodsId());
                                }
                                lotteryRecordEntity.setIsLottery(LotteryRecordStatusEnum.NOT_LOTTERY.getIndex());
                                lotteryRecordDao.update(lotteryRecordEntity);
                                goodsMap.put(goodsEntity, value - 1);
                                recordEntities.remove(nextInt);
                            }

                        }
                    } else {
                        createGoods(recordEntities, goodsMap, random);
                    }
                }
            }
        }
    }


    @Override
    public void downLoad(HttpServletResponse response, List<LotteryActVo> list) {
        try {
            List<LotteryActDown> datas = list.stream().map(item -> new LotteryActDown(item)).collect(Collectors.toList());
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("测试", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            EasyExcel.write(response.getOutputStream(), LotteryActDown.class).sheet("模板").doWrite(datas);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    /**内部方法**/


    /**外部方法实现**/

    /**
     * 查询所有开启的活动
     *
     * @param status
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<LotteryActEntity> findByStatus(Integer status) {

        return dao.findByStatus(status);
    }

    @Autowired
    private UserService userService;

    @Autowired
    private LotteryGoodsService lotteryGoodsService;






    /**
     * 进行抽奖
     *
     * @param userId
     * @param actId
     * @param recordId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public LotteryGoodsEntity startLottery(Long userId, Long actId, Long recordId) {
        LotteryActEntity lotteryActEntity = this.dao.get(actId);
        Date date = new Date();
        if (lotteryActEntity == null) {
            throw new RRException("暂时没有活动");
        }
        if (date.before(lotteryActEntity.getStartTime())) {
            throw new RRException("活动未开始,将于" + lotteryActEntity.getStartTime() + "开始");
        }
        if (date.after(lotteryActEntity.getEndTime())) {
            throw new RRException("活动已结束");
        }

        SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd");

        Integer todayNumber = this.lotteryRecordDao.totalByUserIdTodayNumber(userId, actId, sdf.format(new Date()));
        if (todayNumber > lotteryActEntity.getCount()) {
            throw new RRException("请明天再来抽奖");
        }

        //获取所有未抽奖带有奖品的抽奖记录
        List<LotteryRecordEntity> recordEntities = lotteryRecordDao.findByUserIdAndActIdAndIsLottery(userId, actId, LotteryRecordStatusEnum.LOTTERY.getIndex());
        if (recordEntities != null && recordEntities.size() > 0) {

            //获取抽奖记录
            LotteryRecordEntity lotteryRecordEntity = lotteryRecordDao.get(recordId);
            LotteryGoodsEntity lotteryGoodsEntity = null;
            if (lotteryRecordEntity == null) {
                throw new RRException("您没有中奖");
            }
            //有抽奖记录
            if (lotteryRecordEntity != null) {
                if (lotteryRecordEntity.getIsLottery() != null && lotteryRecordEntity.getIsLottery().equals(LotteryRecordStatusEnum.LOTTERY.getIndex())) {
                    throw new RRException("您本次抽奖已经抽完了，请选择其他抽奖明细抽奖");
                }
                // 判断奖品id是否为空
                if (lotteryRecordEntity.getGoodsId() != null) {
                    lotteryGoodsEntity = lotteryGoodsService.get(lotteryRecordEntity.getGoodsId());
                }
                // 没有奖品自动将最小的奖项赋值
                if (lotteryGoodsEntity == null) {
                    lotteryGoodsEntity = lotteryGoodsService.findMaxGoods(actId);
                    lotteryRecordEntity.setGoodsId(lotteryGoodsEntity.getId());
                    if (lotteryGoodsEntity.getGoodsId() != null) {
                        lotteryRecordEntity.setBandGoodsId(lotteryGoodsEntity.getGoodsId());
                    }
                    lotteryRecordEntity.setGoodsName(lotteryGoodsEntity.getName());
                }

                lotteryRecordEntity.setTime(new Date());
                lotteryRecordEntity.setIsLottery(LotteryRecordStatusEnum.LOTTERY.getIndex());
                lotteryRecordEntity.setStatus(LotteryRecordStatusEnum.NOT_LOTTERY.getIndex());
                lotteryRecordDao.update(lotteryRecordEntity);
                // 计算奖品所在的度数
                if (lotteryGoodsEntity != null) {
                    Integer deg = 0;
                    List<LotteryGoodsEntity> goodsList = this.lotteryGoodsService.findByActIdAndStatus(actId, LotteryGoodsStatusEnum.YES.getIndex());
                    Map<Long, Integer> degMap = deg(goodsList);
                    if (degMap != null && degMap.size() > 0) {
                        deg = degMap.get(lotteryGoodsEntity.getId());
                    }
                    lotteryGoodsEntity.setDeg(deg);
                }
                return lotteryGoodsEntity;
            }

        }


        return null;
    }


    @Autowired
    private AccountService accountService;

    /**
     * 计算每个奖品的度数
     *
     * @param lotteryGoodsEntities
     * @return
     */
    private Map<Long, Integer> deg(List<LotteryGoodsEntity> lotteryGoodsEntities) {
        Integer deg = 0;
        HashMap<Long, Integer> map = new LinkedHashMap<>();
        //计算每个奖品的度数
        for (LotteryGoodsEntity goods : lotteryGoodsEntities) {
            if (goods.getIdx() != 0) {
                deg = deg + goods.getWeight() * 45;
                map.put(goods.getId(), deg);

            } else {

                deg = goods.getWeight() * 45;
                map.put(goods.getId(), deg);
            }
        }
        return map;
    }

    @Autowired
    private LotteryRecordDao lotteryRecordDao;

}
